package com.fishery.logistics.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fishery.entity.GlobalException;
import com.fishery.entity.StatusCode;
import com.fishery.logistics.entity.Order;
import com.fishery.logistics.entity.Path;
import com.fishery.logistics.entity.Station;
import com.fishery.logistics.entity.vo.OrderVo;
import com.fishery.logistics.entity.vo.SearchMap;
import com.fishery.logistics.entity.vo.StationVo;
import com.fishery.logistics.mapper.OrderMapper;
import com.fishery.logistics.mapper.PathMapper;
import com.fishery.logistics.mapper.StationMapper;
import com.fishery.logistics.service.OrderService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fishery.logistics.utils.ConvertUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author run
 * @since 2021-01-23
 */
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private StationMapper stationMapper;

    @Autowired
    private PathMapper pathMapper;

    @Autowired
    private ConvertUtil convertUtil;


    @Override
    @Transactional
    public String createOrder(OrderVo orderVo) {
        StationVo startStation = orderVo.getLogisticsStartStation();
        StationVo arrivalStation = orderVo.getLogisticsArrivalStation();

        if (startStation.getId() != null && startStation.getId().equals(arrivalStation.getId())){
            throw new GlobalException(StatusCode.ERROR,"出发站和抵达站不能重复");
        }

        //对输入的站点信息进行匹配和检查
        matchAndCheckStation(startStation);
        matchAndCheckStation(arrivalStation);

        Order order = convertUtil.convert(orderVo, Order.class);
        //设置出发站和抵达站的id
        order.setLogisticsStartStationId(startStation.getId());
        order.setLogisticsArrivalStationId(arrivalStation.getId());

        order.setId(IdWorker.getIdStr());

        //创建订单的同时也进行出发站的入站操作
        Path path = new Path();
        path.setLogisticsPathStationId(order.getLogisticsStartStationId());
        path.setOrderId(order.getId());
        path.setLogisticsPathArrivalTime(new Date());
        pathMapper.insert(path);

        //如果创建失败
        if (orderMapper.insert(order) == 0){
            throw new GlobalException(StatusCode.ERROR,"物流订单创建失败");
        }
        return order.getId();
    }

    @Override
    public boolean updateOrder(OrderVo orderVo) {
        Order order = orderMapper.selectById(orderVo.getId());
        if (order == null){
            throw new GlobalException(StatusCode.ERROR,"订单不存在");
        }
        if (!order.getBaseId().equals(orderVo.getBaseId())){
            throw new GlobalException(StatusCode.ERROR,"基地id无法修改");
        }
        if (!order.getLogisticsStartStationId().equals(orderVo.getLogisticsStartStation().getId())){
            throw new GlobalException(StatusCode.ERROR,"出发站无法修改");
        }
        if (!order.getLogisticsArrivalStationId().equals(orderVo.getLogisticsArrivalStation().getId())){
            throw new GlobalException(StatusCode.ERROR,"抵达站无法修改");
        }

        order.setProductId(orderVo.getProductId());
        order.setLogisticsOrderCreateBy(orderVo.getLogisticsOrderCreateBy());
        return orderMapper.updateById(order) > 0;
    }

    @Override
    public boolean deleteOrder(String orderId) {
        return orderMapper.deleteById(orderId) > 0;
    }

    @Override
    public Order searchOrderById(String orderId) {
        return addStationMessage(orderMapper.selectById(orderId));
    }

    @Override
    public IPage<Order> searchOrderOfBase(String baseId, Integer page, Integer size, SearchMap searchMap) {
        QueryWrapper<Order> wrapper = new QueryWrapper<>();
        wrapper.eq("base_id",baseId);
        convertMap(wrapper,searchMap);
        Page<Order> orderPage = new Page<>(page,size);

        IPage<Order> result = orderMapper.selectPage(orderPage,wrapper);

        //将出发站和抵达站的站点信息封装进订单对象中
        result.getRecords().forEach((record)->addStationMessage(record));
        return result;
    }

    @Override
    public List<Order> searchOrderOfBase(String baseId, SearchMap searchMap) {
        QueryWrapper<Order> wrapper = new QueryWrapper<>();
        wrapper.eq("base_id",baseId);
        convertMap(wrapper,searchMap);

        List<Order> result = orderMapper.selectList(wrapper);

        //将出发站和抵达站的站点信息封装进订单对象中
        result.forEach((record)->addStationMessage(record));
        return result;
    }

    //将物流站点详细信息封装进物流订单中
    public Order addStationMessage(Order order){
        if (order == null){
            return order;
        }
        order.setLogisticsStartStation(stationMapper.selectById(order.getLogisticsStartStationId()));
        order.setLogisticsArrivalStation(stationMapper.selectById(order.getLogisticsArrivalStationId()));
        return order;
    }

    //进行站点信息的匹配和检查
    public void matchAndCheckStation(StationVo stationVo){
        if (stationVo == null){
            throw new GlobalException(StatusCode.ERROR,"站点无法为空");
        }
        if (stationVo.getId() != null && stationMapper.selectById(stationVo.getId()) == null){
            throw new GlobalException(StatusCode.ERROR,"所选取的站点不存在");
        }
        if (stationVo.getId() == null){

            //如果输入的信息与某个站点匹配，直接复用,否则添加站点
            Station station = findStationByStationMessage(stationVo);
            if (station != null){
                stationVo.setId(station.getId());
            }else {
                Integer type = stationVo.getLogisticsStationType();

                if (type == null || type < 0 || type > 4){
                    throw new GlobalException(StatusCode.ERROR,"站点类型不合法");
                }
                stationVo.setId(IdWorker.getIdStr());
                stationMapper.insert(convertUtil.convert(stationVo, Station.class));
            }
        }
    }

    private Station findStationByStationMessage(StationVo stationVo){
        Map<String,Object> map = new HashMap<>(6,1);
        map.put("logistics_station_address",stationVo.getLogisticsStationAddress());
        map.put("logistics_station_longitude",stationVo.getLogisticsStationLongitude());
        map.put("logistics_station_latitude",stationVo.getLogisticsStationLatitude());
        map.put("logistics_station_type",stationVo.getLogisticsStationType());
        map.put("base_id",stationVo.getBaseId());
        map.put("phone_number",stationVo.getPhoneNumber());

        List<Station> stations = stationMapper.selectByMap(map);
        return stations.isEmpty() ? null : stations.get(0);
    }

    private void convertMap(QueryWrapper<Order> queryWrapper, SearchMap searchMap){
        if (searchMap == null) {
            return;
        }
        Integer status = searchMap.getStatus();
        Integer sort = searchMap.getSort();
        if (status == 0 || status == 1){
            queryWrapper.eq("logistics_order_status", status);
        }
        if (sort == 0 || sort == 1){
            if (sort == 0){
                queryWrapper.orderByAsc("gmt_create");
            }else {
                queryWrapper.orderByDesc("gmt_create");
            }

        }
    }
}
